<?php
require_once 'db.php';
require_once 'adminClass.php';
define ('SALT', 'ThisIsth3sal7'); // NEVER CHANGE!
define ('SITEKEY', 'ASiteSpecificArbitraryLengthStringThatIsUsedToSeedTheHashingAlgorithm'); //NEVER CHANGE!

/**
 *
 * @author Eivind Parken
 * @var user class
 */
class user {
	/** Users login name String(50) */
	var $userName = '';	
	/** users uniqe ID int */
	var	$userID = -1;
	/** Users Real Name string(50)*/
	var $userRealName;
	/** User Email string(50) */
	var $email;
	/** Users hometown string(50) */
	var $homeTown;
	/** Users birthyear int(4) */
	var $birthYear;
	/** user choosen theme int */
	var	$theme = 1;
	/** user avatar */
	var $avatar;	
	/** Error variable for errors string */
	var $error = '';
	/** Database PDO object */
	var $db;
	/** Is the user administrator? */
	var $isAdmin = false;
	/** Is the user blocked? */
	var $isBlocked = false;
	
	/**
	 * Finding user in DB, and their personal settings
	 * and "creating" a user object
	 * @param object $db PDO Object
	 */
	function __construct($db){
		global $_POST, $_SESSION;
		$this -> db = $db;
		if(isset ($_POST['loginName'])){
			$this -> userName = $_POST['loginName'];
			$query = 'SELECT * FROM user WHERE userName=:usrName';
			$sql = $db -> prepare($query);
			$sql -> bindParam(':usrName', $this -> userName);		
			$sql -> execute();			
			$user = $sql -> fetch();
			if($user){
				$uid = $user['userID'];
				$user = NULL;
				$query = 'SELECT * FROM user WHERE userID=:userID and password=:pwd';
				$user = $db -> prepare($query);
				$user -> bindParam(':userID', $uid);
				$pwd = $uid.$_POST['pwd'].SALT;
				$pwdhashed =  hash_hmac('sha512', $pwd, SITEKEY);		
				$user -> bindParam(':pwd', $pwdhashed);
				$user -> execute();
				$user = $user->fetch();
				if($user){ 				//Gather data from DB to user object
					$this -> userID = $user['userID'];
					session_regenerate_id(true);
					$_SESSION['usrID'] = $user['userID'];
					$this -> userRealName = $user['userRealName'];
					$this -> birthYear = $user['birthYear'];
					$this -> email = $user['email'];
					$this -> homeTown = $user['homeTown'];
					$this -> theme = $user['themeID'];
					$this -> avatar = $user['profilePicture'];
					$this -> isAdmin = $user['isAdmin'];
					$this -> isBlocked = $user['isBlocked'];
					return;
				}				
			}
			$this -> error = 'Unknown username or password!<br/>';
		}else if(isset($_POST['logout'])){
			unset ($_SESSION['usrID']);
		}else if(isset($_SESSION['usrID'])){
			$this -> userID = $_SESSION['usrID'];
			$query = 'SELECT * FROM user WHERE userID=:usrID';
			$sql = $db -> prepare($query);
			$sql -> bindParam(':usrID', $_SESSION['usrID']);
			$sql -> execute();
			$user = $sql -> fetch();
			$this -> userName = $user['userName'];
			$this -> userRealName = $user['userRealName'];
			$this -> birthYear = $user['birthYear'];
			$this -> email = $user['email'];
			$this -> homeTown = $user['homeTown'];		
			$this -> theme = $user['themeID'];
			$this -> avatar = $user['profilePicture'];
			$this -> isAdmin = $user['isAdmin'];
			$this -> isBlocked = $user['isBlocked'];
		}
	}
	
	/**
	 * Add a new user to database
	 * @param arrau $files Uploaded files
	 * @param array $post content of form 
	 * @throws Exception Error messages when creating a user
	 */	
	function createUser($files, $post){
		$usrPic = NULL;
		// If there is an uploaded image:
		if (isset($files['usrImg']) && is_uploaded_file($files['usrImg']['tmp_name'])) {
			$maxWidth = 200;
			$maxHeight = 200;
			list($width, $height) = getimagesize($files['usrImg']['tmp_name']);
			$factor1 = $height/$maxHeight;
			$factor2 = $width/$maxWidth;
			$factor = ($factor1>$factor2)?$factor1:$factor2;
			$new_width = $width / $factor;
			$new_height = $height / $factor;
			$image_p = imagecreatetruecolor($new_width, $new_height);
			$image = imagecreatefromstring(file_get_contents($files['usrImg']['tmp_name']));
			imagecopyresampled($image_p, $image, 0, 0, 0, 0, $new_width, $new_height, $width, $height);
			ob_start();
			ob_clean();
			imagepng($image_p);
			$usrPic = ob_get_contents();
			ob_end_clean();
		}
		// Ser variables depending on if user filled them out:
		$usrName = $post['usrName'];
		$pwd = $post['pwd1'];
		if (!isset($post['name']) || $post['name'] == "") {
			$name = NULL;
		}
		else {
			$name = $post['name'];
		}
		if (!isset($post['birth']) || $post['birth'] == "") {
			$birth = NULL;
		}
		else {
			$birth = $post['birth'];
		}
		$email = $post['email'];
		if (!isset($post['homeTown']) || $post['homeTown'] == "") {
			$homeTown = NULL;
		}
		else {
			$homeTown = $post['homeTown'];
		}
		$theme = $post['theme'];
		
		try{			
			$this -> db -> beginTransaction();
			$this -> db -> query('LOCK TABLES user WRITE');
			$query = 'INSERT INTO user (userName, userRealName, birthYear, email, homeTown, themeID,
					 					profilePicture) 
					  VALUES (:usrName, :realName, :birth, :email, :town, :theme, :pic)';
			$usr = $this -> db -> prepare($query);
			$usr -> bindParam(':usrName', $usrName);
			$usr -> bindParam(':realName', $name);
			$usr -> bindParam(':birth', $birth);
			$usr -> bindParam(':email', $email);
			$usr -> bindParam(':town', $homeTown);
			$usr -> bindParam(':theme', $theme);
			$usr -> bindParam(':pic', $usrPic);
			$usr -> execute();
			if($usr -> rowCount() == 0){
				$this -> db -> rollback();
				$this -> db -> query('UNLOCK TABLES');
				throw new Exception('Username or email already exists!');
			}
			
			$usr -> closeCursor();
			$usr = $this -> db -> prepare('SELECT LAST_INSERT_ID() AS usrID');
			$usr -> execute();
			$usr = $usr -> fetch();
			if($usr){
				$uid = $usr['usrID'];
			}else{
				$this -> db -> rollback();
				$this -> db -> query('UNLOCK TABLES');
				throw new Exception('Error getting new user id!');
			}
			$usr = NULL;
			$query = 'UPDATE user SET password=:pwd WHERE userID=:usrID';
			$usr = $this -> db -> prepare($query);
			$usr -> bindParam(':usrID', $uid);
			$pwd = $uid.$pwd.SALT;
			$usr -> bindParam(':pwd', hash_hmac('sha512', $pwd, SITEKEY));
			$usr -> execute();
			if($usr -> rowcount() == 0){
				$this -> db -> rollBack();
				$this -> db -> query('UNLOCK TABLES');
				throw new Exception('Unable to set password!');
			}
			
			// Define path where file will be uploaded to
			//   User ID is set as directory name
			$folderPath= "media";
			$folderPath2 = "media/{$uid}";
	
			// Check to see if directory already exists
			$exist = is_dir($folderPath);
			$exist2 = is_dir($folderPath);
			// If directory doesn't exist, create directory
			if(!$exist){
				mkdir("$folderPath");
				chmod("$folderPath", 0755);
			}
			if(!$exist2) {
				mkdir("$folderPath2");
				chmod("$folderPath2", 0755);
			}
			$this -> db -> commit();
			$_SESSION['usrID'] = $uid;
			return true;
		} catch(Exception $e) {
			$this -> db -> rollBack();
			if($e->getCode()==23000){
				$this -> error = 'Kunne ikke registere ny bruker: Brukernavn er allerede registert...';
				return false;
			}else{
				echo $this -> error = 'Kunne ikke registere ny bruker: '.$e -> getMessage();
				return false;
			}		
		}	
	}
	
	/**
	 * Checks if password sent equals the one in use
	 * @param sting $pass Password
	 * @return boolean true, if password is correct
	 */
	function correctPass($pass){
		$uid = $this->userID;
		$query = 'SELECT userName
				FROM user
				WHERE userID=:usrID AND password=:pwd';
		$usr = $this -> db -> prepare($query);
		$usr -> bindParam(':usrID', $uid);
		$pass = $uid.$pass.SALT;
		$usr -> bindParam(':pwd', hash_hmac('sha512', $pass, SITEKEY));
		$usr -> execute();
		return ($usr->fetch())? false:true;	
	}
	
	/**
	 * If user is logged in the userID value will be changed a value higher than -1
	 * @return boolean true, if user are logged in 
	 */
	function userLoggedOn(){
		return ($this -> userID > -1)? true : false;	
	}
	/**
	 * Returns Userid if user is logged on, or NULL if not
	 * @return number|NULL
	 */
	function getUserID(){
		if($this -> userLoggedOn()){
			return $this -> userID;
		}else{
			return NULL;
		}
	}
	/**
	 * If username = postID, get userID altso
	 * If username = username get userinfo
	 * If parameter == false, this user, so get data from object
	 * @param string $userName
	 * @return multitype:string number boolean NULL |unknown|NULL
	 */
	function getUserInfo($userName){
		if(isset($userName)){
			if(is_numeric($userName)){ // If $username is numeric it means it is a PostID numnber and we need get the author
				$sql = "SELECT userName, isAdmin, userRealName, birthYear, homeTown, userID, isBlocked
						FROM user LEFT JOIN post ON username=author
						WHERE postId=:postId";
				$sth = $this -> db -> prepare ($sql);
				$sth -> bindParam (':postId', $userName);
				$sth -> execute ();
				$sth = $sth -> fetch(PDO::FETCH_ASSOC);
				return $sth;
			}else{ 					// If $username is text, it means its a username
				$sql = "SELECT userName, isAdmin, userRealName, birthYear, homeTown, isBlocked  FROM user WHERE userName=:usrName";
				$sth = $this -> db -> prepare ($sql);
				$sth -> bindParam (':usrName', $_GET['usrName']);
				$sth -> execute ();
				$sth = $sth -> fetch(PDO::FETCH_ASSOC);
				return $sth;
			}
		}else{ 			// If $username is empty it means its the logged in user that want to display his profile
			return array(
					"userName" => $this -> userName,
					"userRealName" => $this -> userRealName,
					"homeTown" => $this -> homeTown,
					"birthYear" => $this -> birthYear,
					"isAdmin" => $this -> isAdmin,
					"isBlocked" => $this -> isBlocked
					);
		}
	}
	/**
	 * Echos out user information on display profile and blog post,
	 * @param array $user
	 */
	function showUserInfo($user){
		$thisYear = date('Y');
		echo "<h2 class='blogg'><a href='displayUsr.php?usrName=".$user['userName']."'>".$user['userName']."</a></h2>";
		// If blocked show default image
		if ($user['isBlocked']) {
			echo "<img src='include/displayFile.php?blocked=1' />";
		}
		// Else show profile picture
		else {
			// Checks if user ID is in the array, if so the page that is loaded is a showpost
			echo "<img src='include/displayFile.php?".((array_key_exists("userID", $user)?"usrID={$user['userID']}":"usrName={$_GET['usrName']}"))."' />";
		}
		echo "<p><b>Brukerinformasjon</b><br/>";
		if($user['isBlocked']) {
			echo "Denne brukeren har blitt blokkert av administrator.</p>";
		}
		else {
			echo "Brukertype: ";
			echo (($user['isAdmin'] == false)? "Bruker": "Administrator");
			echo (!is_null($user['userRealName']))? "<br/>Navn: {$user['userRealName']}" : "";
			echo (!is_null($user['birthYear']))? "<br/>Alder: ".($thisYear - $user['birthYear'])." år" : "";
			echo (!is_null($user['homeTown']))? "<br/>Hjemsted: {$user['homeTown']}" : "";
			echo "</p>";
		}
	}
	
	/**
	 * Returns location to css the user have choosen
	 * if non, default css is returned
	 * @return Location to CSS as string
	 */
	function getUserTheme($site){
		$re = '/^[a-zA-Z][a-zA-Z0-9-_\.]{1,20}$/';
		if($site == false){
				echo "css/blue.css";
		}else if(is_numeric($site)){
			$query = "SELECT theme.location  FROM user
			LEFT JOIN theme on themeID=theme.id
			LEFT JOIN post on userName=author WHERE postId=:postId";
			$result = $this -> db -> prepare($query);
			$result -> bindParam(':postId', $site);
			$result -> execute();
			$res = $result -> fetch();
			echo $res['location'];
		}else if(preg_match($re,$site)){
			$query = "SELECT theme.location  FROM user
			LEFT JOIN theme on themeID=theme.id
			WHERE userName=:usrName";
			$result = $this -> db -> prepare($query);
			$result -> bindParam(':usrName', $site);
			$result -> execute();
			$res = $result -> fetch();
			echo $res['location'];
		}else if($this -> userLoggedOn()){
			$query = "SELECT theme.location FROM user
			LEFT JOIN theme on themeID=theme.id WHERE userID=$this->userID";
			$result = $this -> db -> prepare($query);
			$result -> execute();
			$res = $result -> fetch();
			echo $res['location'];
		}	
	}
	
	/**
	  * If user are logged in, the loginform will only have a sign out option
	  * If user are not signed in he can input his username and password.
	  */
	function getLoginForm(){
		if($this -> userLoggedOn()){
			return "<form method='post' action='{$_SERVER['REQUEST_URI']}'>
			<input type='hidden' name='logout' value='true'/>
			<input type='submit' value='Logg ut'/></form>";
		}else{
			return "<form method='post' action='{$_SERVER['REQUEST_URI']}'>$this->error\n
				<label for='usrName'>Brukernavn</label><input type='text' name='loginName'/>\n
				<label for='pwd'>Passord</label><input type='password' name='pwd'/>\n
				<input type='submit' value='Logg inn'/></form>";
		}
	}
	/**
	 * Returns if a user realy is a Administrator
	 * @return boolean
	 */
	function isUserAdmin(){
		return $this->isAdmin;
	}
	/**
	 * Edit user in database
	 * @param arrau $files Uploaded files
	 * @param array $post content of form
	 * @throws Exception
	 */
	function editUser($files, $post){
		$usrPic = NULL;
		// If there is a piucture:
		if (isset($files['usrImg']) && is_uploaded_file($files['usrImg']['tmp_name'])) {
			$maxWidth = 200;
			$maxHeight = 200;
			list($width, $height) = getimagesize($files['usrImg']['tmp_name']);
			$factor1 = $height/$maxHeight;
			$factor2 = $width/$maxWidth;
			$factor = ($factor1>$factor2)?$factor1:$factor2;
			$new_width = $width / $factor;
			$new_height = $height / $factor;
			$image_p = imagecreatetruecolor($new_width, $new_height);
			$image = imagecreatefromstring(file_get_contents($files['usrImg']['tmp_name']));
			imagecopyresampled($image_p, $image, 0, 0, 0, 0, $new_width, $new_height, $width, $height);
			ob_start();
			ob_clean();
			imagepng($image_p);
			$usrPic = ob_get_contents();
			ob_end_clean();
		}
		
		// Set variables depending on wheter set:
		if(!isset($post['pwd1']) || $post['pwd1'] == "") {
			$pwd = NULL;
		}
		else {
			$pwd = $post['pwd1'];
		}
		if (!isset($post['name']) || $post['name'] == "") {
			$name = NULL;
		}
		else {
			$name = $post['name'];
		}
		if (!isset($post['birth']) || $post['birth'] == "") {
			$birth = NULL;
		}
		else {
			$birth = $post['birth'];
		}
		$email = $post['email']; 
		if (!isset($post['homeTown']) || $post['homeTown'] == "") {
			$homeTown = NULL;
		}
		else {
			$homeTown = $post['homeTown'];
		}
		$theme = $post['theme'];
		
		
		$uid = $this -> userID;
		$db = $this -> db;
		$db -> beginTransaction();
		$db -> query('LOCK TABLES user WRITE');
		$query = 'UPDATE user SET userRealName=:realName, birthYear=:birth, email=:email, homeTown=:town, themeID=:theme';
		if(isset($usrPic)){
			$query .= ", profilePicture=:pic";
		}
		$query .= " WHERE userId=:usrId";
		$usr = $db -> prepare($query);
		$usr -> bindParam(':realName', $name);
		$usr -> bindParam(':birth', $birth);
		$usr -> bindParam(':email', $email);
		$usr -> bindParam(':town', $homeTown);
		$usr -> bindParam(':theme', $theme);
		if(isset($usrPic)){
			$usr -> bindParam(':pic', $usrPic);
		}
		$usr -> bindParam(':usrId', $this -> userID);
		$usr -> execute();
		if($usr -> rowCount() == 0){
			$db -> rollback();
			$db -> query('UNLOCK TABLES');
			throw new Exception('Error while doing update on userdata!');
		}
		$usr -> closeCursor();
		// If new password is set:
		if($pwd != NULL) {
			$query = 'UPDATE user SET password=:pwd WHERE userID=:usrID';
			$usr = $db -> prepare($query);
			$usr -> bindParam(':usrID', $uid);
			$pwd = $uid.$pwd.SALT;
			$usr -> bindParam(':pwd', hash_hmac('sha512', $pwd, SITEKEY));
			$usr -> execute();
			if($usr -> rowcount() == 0){
				$db -> rollBack();
				$db -> query('UNLOCK TABLES');
				throw new Exception('Unable to update password!');
			}
		}
		
		$db -> commit();
	}
	
	
	/**
	 * Cheks if a user has already been reported by same reporter
	 * @param sting $usrName Reported users screenname
	 * @return bool True/false to either already reported by same user
	 */
	function hasReported($usrName) {
		$uname = $this -> userName;
		$db = $this -> db;
		$sql = "SELECT userNameReported, userNameReporter
						FROM userReport
						WHERE userNameReported=:usrName AND userNameReporter=:usrRep";
		$sth = $this -> db -> prepare ($sql);
		$sth -> bindParam (':usrName', $usrName);
		$sth -> bindParam (':usrRep', $uname);
		$sth -> execute ();
		$sth = $sth -> fetch(PDO::FETCH_ASSOC);
		if($sth) {
			return true;
		}
		else {
			return false;
		}
	}
	
	/**
	 * Updates DB with info of reported user
	 * @param sting $usrName Reported users screenname
	 * @param string $text report text
	 */
	function report_user($usrName, $text) {
		$uname = $this -> userName;
		$db = $this -> db;
		$db -> beginTransaction();
		$query = 'INSERT INTO userReport (userNameReported, userNameReporter, comment) 
				  VALUES (:usrName, :userReporter, :comment)';
		$usr = $db -> prepare($query);
		$usr -> bindParam(':usrName', $usrName);
		$usr -> bindParam(':userReporter', $uname);
		$usr -> bindParam(':comment', $text);
		$usr -> execute();
		if($usr -> rowCount() == 0){
			$db -> rollback();
			$db -> query('UNLOCK TABLES');
			throw new Exception('Error while reporting user');
		}
		$db -> commit();
	}
}




$user = new user($db);

/**
 * If admin, create admin object
 */
if($user->isUserAdmin()){
	$admin = new admin($db);
}
?>